{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "start videostream\n",
      "start image\n",
      "Right\n",
      "Right\n",
      "Right\n",
      "Right\n",
      "Right\n",
      "Right\n",
      "Right\n",
      "Right\n",
      "Right\n",
      "Right\n",
      "Right\n",
      "Right\n",
      "Right\n",
      "Right\n",
      "Right\n",
      "Right\n",
      "Right\n",
      "Right\n",
      "Right\n",
      "Right\n",
      "Right\n",
      "Right\n",
      "Right\n",
      "Left\n",
      "Left\n"
     ]
    }
   ],
   "source": [
    "import threading\n",
    "import socketserver\n",
    "import serial\n",
    "import cv2\n",
    "import numpy as np\n",
    "import math\n",
    "import sys\n",
    "import urllib.request\n",
    "import socket\n",
    "import struct\n",
    "\n",
    "\n",
    "class NeuralNetwork(object):\n",
    "#神经网络用的是opencv 自带的 ANN_MLP\n",
    "    def __init__(self):\n",
    "        self.model = cv2.ml.ANN_MLP_load('D:/F/Study/SelfDirveCar_OpenCV_MLP_RaspberryPi/mlp_xml/mlp_1560440216.xml')\n",
    "        #输入层是 38400  -> 32 ,其中 38400 是图片大小\n",
    "        #从`mlp_xml/mlp.xml`加载网络结构和参数\n",
    "\n",
    "\n",
    "    def predict(self, samples):\n",
    "        ret, resp = self.model.predict(samples)\n",
    "        return resp.argmax(-1)\n",
    "        #预测下一步的动作\n",
    "\n",
    "class RCControl(object):\n",
    "\n",
    "    def __init__(self):\n",
    "          self.ser = serial.Serial('COM5', 9600, timeout=1)\n",
    "\n",
    "    def steer(self, prediction):\n",
    "        if prediction == 2:\n",
    "            self.ser.write(b'51')\n",
    "            print(\"Forward\")\n",
    "        elif prediction == 0:\n",
    "            self.ser.write(b'53')\n",
    "            print(\"Left\")\n",
    "        elif prediction == 1:\n",
    "            self.ser.write(b'49')\n",
    "            print(\"Right\")\n",
    "        else:\n",
    "            self.stop()\n",
    "\n",
    "    def stop(self):\n",
    "        self.ser.write(b'48')\n",
    "        #根据预测值控制小车的方向\n",
    "        #只有四种情况，2：向前，0：向左，1：向右，其他：不动。\n",
    "\n",
    "\n",
    "\n",
    "class VideoStreamHandler(socketserver.StreamRequestHandler):\n",
    "#视频流处理\n",
    "        print('start videostream')\n",
    "    \n",
    "\n",
    "        model = NeuralNetwork()\n",
    "\n",
    "        car = RCControl()\n",
    "\n",
    "        def handle(self):      \n",
    "                print('start image')\n",
    "                # 获取视频帧\n",
    "                try:\n",
    "\n",
    "                    while True:\n",
    "                        image_len = struct.unpack('<L', self.rfile.read(struct.calcsize('<L')))[0]\n",
    "                        if not image_len:\n",
    "                                break\n",
    "\n",
    "                        recv_bytes = b''\n",
    "                        recv_bytes += self.rfile.read(image_len)\n",
    "                        gray = cv2.imdecode(np.frombuffer(recv_bytes, dtype=np.uint8), cv2.IMREAD_GRAYSCALE)\n",
    "                        image = cv2.imdecode(np.frombuffer(recv_bytes, dtype=np.uint8), cv2.IMREAD_COLOR)\n",
    "\n",
    "                            # 取下半部分图像做特征向量\n",
    "                        roi = gray[120:240, :]\n",
    "\n",
    "                            # 拼接完整图像\n",
    "                        image_array = roi.reshape(1, 38400).astype(np.float32)                     \n",
    "                        cv2.imshow('image',image)\n",
    "                       \n",
    "    \n",
    "\n",
    "                            # 预测\n",
    "                        prediction = self.model.predict(image_array)\n",
    "\n",
    "                            # 传输给小车\n",
    "\n",
    "                        self.car.steer(prediction)\n",
    "  \n",
    "\n",
    "                    cv2.destroyAllWindows()\n",
    "\n",
    "                finally:\n",
    "\n",
    "                    print(\"Connection closed on the server video thread!\")\n",
    "\n",
    "\n",
    "    \n",
    "class ThreadServer(object):\n",
    "#线程管理器\n",
    "    def server_thread(host, port):\n",
    "        server = socketserver.TCPServer((host, port), VideoStreamHandler)  #实例化线程\n",
    "        server.serve_forever()\n",
    "\n",
    "    video_thread = threading.Thread(target=server_thread('0.0.0.0', 10000)) \n",
    "    video_thread.start()\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    ThreadServer() \n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
